use crate::cljcell::clj_cell::CljCell;
use crate::built_in_functions::clj_funs::CljFunctions;
use crate::built_in_functions::my_funs::MyFunctions;
use crate::built_in_functions::clj_math::MyMath;
use crate::built_in_functions::clj_logic::MyLogic;
use crate::built_in_functions::clj::MyClj;
use crate::built_in_functions::clj_data::MyCljData;
use crate::built_in_functions::clj_macro::MyMacro;
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;

/**
 *  Function 的定义
 */
#[derive(Debug, Default)]
pub struct CljFuncParamList {
    name: String
}

impl CljFuncParamList {
    pub fn new(name: String) -> Self {
        Self {
            name: name
        }
    }

    pub fn get_name(&self) -> &String {
        &self.name
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name
    }
}

impl fmt::Display for CljFuncParamList {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //write!(f, "Person(name: {}, age: {})", to_string(&self))
        write!(f, "CljFuncParamList(name: {})", self.name)
    }
}

/**
 * 函数参数
 * */
#[derive(Debug, Default)]
pub struct CljFuncParam {
    name: String,
    rest_param: String,
    clj_func_param_list: Vec<Rc<CljFuncParamList>>
}

impl CljFuncParam {
    pub fn new(name: String) -> Self {
        Self {
            name: name,
            rest_param: String::new(),
            clj_func_param_list: Vec::new(),
        }
    }

    pub fn new1() -> Self {
        Self {
            name: String::new(),
            rest_param: String::new(),
            clj_func_param_list: Vec::new(),
        }
    }

    pub fn get_name(&self) -> &String {
        &self.name
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name
    }

    pub fn get_rest_param(&self) -> &String {
        &self.rest_param
    }

    pub fn set_rest_param(&mut self, rest_param: String) {
        self.rest_param = rest_param
    }

    pub fn get_clj_func_param_list(&self) -> &Vec<Rc<CljFuncParamList>> {
        &self.clj_func_param_list
    }

    pub fn set_clj_func_param_list(&mut self, clj_func_param_list: Vec<Rc<CljFuncParamList>>) {
        self.clj_func_param_list = clj_func_param_list
    }

    pub fn to_string(&self) -> String {
        let mut sb = String::new();
        if !self.name.is_empty() {
            sb.push_str(&self.name);
        } else if !self.rest_param.is_empty() {
            sb.push_str(&self.rest_param);
        } else if !self.clj_func_param_list.is_empty() {
            sb.push_str("[");
            unsafe {
                for m in &self.clj_func_param_list {
                    let p: *mut CljFuncParamList = Rc::into_raw(m.clone()) as *mut CljFuncParamList;
                    sb.push_str((*p).get_name());
                    Rc::from_raw(p);
                }
            }
            sb.push_str("]");
        }
        return sb;
    }

    // pub fn to_string(&self) -> String {
    //     let mut sb = String::new();
    //     println!("{:?}", self.CljFuncParamList);
    //     if !self.CljFuncParamList.is_empty() {
    //         sb.push_str("[");
    //         for m in &self.CljFuncParamList {
    //             sb.push_str(m.get_name());
    //         }
    //         sb.push_str("]");
    //     }
    //     return sb;
    // }
}

impl fmt::Display for CljFuncParam {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //write!(f, "Person(name: {}, age: {})", to_string(&self))
        write!(f, "CljFuncParam(name: {}, rest_param: {}, CljFuncParamList: {})", self.name, self.rest_param, self.to_string())
    }
}

/**
 * clojure 函数存在 函数符号表
 * */
#[derive(Debug)]
pub struct CljFunc {
    func_params: Vec<Rc<CljFuncParam>>,
    func_body: Rc<CljCell>
}

impl Default for CljFunc {
    fn default() -> Self {
        Self {
            func_params: Vec::new(),
            func_body: Rc::new(CljCell::Null),
        }
    }
}

impl CljFunc {
    pub fn new(func_params: Vec<Rc<CljFuncParam>>, func_body: Rc<CljCell>) -> Self {
        Self {
            func_params: func_params,
            func_body: func_body,
        }
    }

    pub fn get_func_params(&self) -> &Vec<Rc<CljFuncParam>> {
        &self.func_params
    }

    pub fn set_name(&mut self, func_params: Vec<Rc<CljFuncParam>>) {
        self.func_params = func_params
    }

    pub fn get_func_body(&self) -> &Rc<CljCell> {
        &self.func_body
    }

    pub fn set_func_body(&mut self, func_body: Rc<CljCell>) {
        self.func_body = func_body
    }

    pub fn to_string(&self) -> String {
        let mut sb = String::from("[");
        unsafe {
            for i in 0..self.func_params.len() {
                let m = &self.func_params[i];
                //println!("{:?}", m);
                if i == self.func_params.len() - 1 {
                    let p: *mut CljFuncParam = Rc::into_raw(m.clone()) as *mut CljFuncParam;
                    sb.push_str(&(*p).to_string());
                    Rc::from_raw(p);
                    //sb.push_str(&m.to_string());
                    //println!("{:?}", m);
                } else {
                    let p: *mut CljFuncParam = Rc::into_raw(m.clone()) as *mut CljFuncParam;
                    sb.push_str(&(*p).to_string());
                    Rc::from_raw(p);
                    // sb.push_str(&m.to_string());
                    // sb.push_str(" ");
                }
            }
        }
        sb.push_str("]");
        sb.push_str(&self.func_body.to_string());
        return sb;
    }
}

impl fmt::Display for CljFunc {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //write!(f, "Person(name: {}, age: {})", to_string(&self))
        write!(f, "CljFunc({})", self.to_string())
    }
}

/**
 * CljFunc
 * */
#[derive(Debug, Default)]
pub struct MyCljFunc {
    is_override: bool,
    clj_func: CljFunc,
    pub func_override: HashMap<i32, CljFunc>,
    pub flag: bool
}

impl MyCljFunc {
    pub fn new(clj_func: CljFunc) -> Self {
        Self {
            is_override: false,
            clj_func: clj_func,
            func_override: HashMap::new(),
            flag: false
        }
    }

    pub fn new1(is_override: bool) -> Self {
        Self {
            is_override: is_override,
            func_override: HashMap::new(),
            flag: false,
            ..Default::default()
        }
    }

    pub fn to_string(&self) -> String {
        let mut sb = String::new();
        if self.is_override {
            sb.push_str("is_override: true");
        } else {
            sb.push_str("is_override: false");
        }
        sb.push_str("CljFunc: ");
        sb.push_str(&self.clj_func.to_string());

        sb.push_str("func_override: [");
        sb.push_str(&self.clj_func.to_string());
        sb.push_str("]");
        return sb;
    }

    pub fn get_is_override(&self) -> &bool {
        &self.is_override
    }

    pub fn set_is_override(&mut self, is_override: bool) {
        self.is_override = is_override
    }

    pub fn get_clj_func(&self) -> &CljFunc {
        &self.clj_func
    }

    pub fn set_clj_func(&mut self, clj_func: CljFunc) {
        self.clj_func = clj_func
    }

    pub fn get_func_override(&self) -> &HashMap<i32, CljFunc> {
        &self.func_override
    }

    pub fn set_func_override(&mut self, func_override: HashMap<i32, CljFunc>) {
        self.func_override = func_override
    }

    pub fn get_clj_func_1(&self, psum: i32) -> Option<&CljFunc> {
        if self.is_override {
            if self.get_func_override().contains_key(&psum) {
                return self.get_func_override().get(&psum);
            } else {
                // for vs in self.get_func_override().values() {
                //     let num = vs.get_func_params().len() - (1 as usize);
                //     if vs.get_func_params().len() <= (psum as usize) && vs.get_func_params().get(num).is_some() {
                //         return Some(vs);
                //     }
                // }
                let mut i = 0;
                for k in self.get_func_override().keys() {
                    if k > &i {
                        i = *k;
                    }
                }
                return self.get_func_override().get(&i);

            }
        }
        return None;
    }
}

impl fmt::Display for MyCljFunc {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //write!(f, "Person(name: {}, age: {})", to_string(&self))
        write!(f, "MyCljFunc({})", self.to_string())
    }
}

/**
 * CljRecur
 * */
#[derive(Debug)]
pub struct CljRecur {
    pub ht: HashMap<i32, String>,
    pub clj_cell: Rc<CljCell>,
    pub func_cell_body: Rc<CljCell>,
    pub clj_func_param_list: Vec<Rc<CljFuncParam>>
}

impl CljRecur {
    pub fn new() -> Self {
        Self {
            ht: HashMap::new(),
            clj_cell: Rc::new(CljCell::Null),
            func_cell_body: Rc::new(CljCell::Null),
            clj_func_param_list: Vec::new(),
        }
    }

    pub fn get_ht_mut(&self) -> HashMap<i32, String> {
        self.ht.clone()
    }

    pub fn get_ht(&self) -> &HashMap<i32, String> {
        &self.ht
    }

    pub fn set_ht(&mut self, ht: HashMap<i32, String>) {
        self.ht = ht
    }

    pub fn get_clj_cell(&self) -> &Rc<CljCell> {
        &self.clj_cell
    }

    pub fn set_clj_cell(&mut self, clj_cell: Rc<CljCell>) {
        self.clj_cell = clj_cell
    }

    pub fn get_func_cell_body(&self) -> &Rc<CljCell> {
        &self.func_cell_body
    }

    pub fn set_func_cell_body(&mut self, func_cell_body: Rc<CljCell>) {
        self.func_cell_body = func_cell_body
    }

    pub fn get_clj_func_param_list(&self) -> &Vec<Rc<CljFuncParam>> {
        &self.clj_func_param_list
    }

    pub fn set_clj_func_param_list(&mut self, clj_func_param_list: Vec<Rc<CljFuncParam>>) {
        self.clj_func_param_list = clj_func_param_list
    }
}

#[derive(Debug)]
pub struct FuncParams {
    fps: HashMap<String, MyCljFunc>
}

impl FuncParams {
    pub fn new() -> Self {
        Self {
            fps: HashMap::new()
        }
    }

    pub fn get_fps(&self) -> &HashMap<String, MyCljFunc> {
        &self.fps
    }

    pub fn set_fps(&mut self, fps: HashMap<String, MyCljFunc>) {
        self.fps = fps
    }

    pub fn set_vs(&mut self, key: String, vs: MyCljFunc) {
        self.fps.insert(key, vs);
    }

    pub fn get_vs(&self, key: &String) -> Option<&MyCljFunc> {
        self.fps.get(key)
    }

    pub fn get_contains_key(&self, key: &String) -> bool {
        self.fps.contains_key(key)
    }

}

/**
 * 对 func_hs 的操作
 * */
#[derive(Debug)]
pub struct MyFuncHs {
    pub ptr: *mut HashMap<String, Rc<CljCell>>,
}

impl MyFuncHs {
    pub fn new() -> Self {
        Self {
            ptr: Box::into_raw(Box::new(HashMap::new())),
        }
    }

    pub fn new1(ht: HashMap<String, Rc<CljCell>>) -> Self {
        Self {
            ptr: Box::into_raw(Box::new(ht)),
        }
    }

    pub fn contains_key(&self, key: &String) -> bool {
        unsafe {
            (*self.ptr).contains_key(key)
        }
    }

    /**
     * 获取 func_hs 中的值
     * */
    pub fn get(&self, key: &String) -> &Rc<CljCell> {
        unsafe {
            let rs = (*self.ptr).get(key);
            if rs.is_some() {
                return rs.unwrap();
            }
            panic!("函数的参数个数和定义的不一致！");
        }
    }
    // pub fn get(&self, key: &String) -> Result<&Rc<CljCell>, &str> {
    //     unsafe {
    //         let rs = (*self.ptr).get(key);
    //         if rs.is_some() {
    //             return Ok(rs.unwrap());
    //         } else {
    //             return Err("函数的参数个数和定义的不一致！");
    //         }
    //         //(*self.ptr).get(key).unwrap()
    //     }
    // }

    /**
     * 添加值
     * */
    pub fn insert(&self, key: String, vs: Rc<CljCell>) -> Option<Rc<CljCell>> {
        unsafe {
            (*self.ptr).insert(key, vs)
        }
    }

    /**
     * 添加所有值
     * */
    pub fn insert_all(&self, ht: HashMap<String, Rc<CljCell>>) {
        for (k, v) in &ht {
            unsafe {
                (*self.ptr).insert(k.to_string(), v.clone());
            }
        }
    }
}

// 手动实现 Drop 释放内存
impl Drop for MyFuncHs {
    fn drop(&mut self) {
        unsafe {
            let _ = Box::from_raw(self.ptr);
        }
    }
}

/**
 * 对 func_hs 的操作
 * */
#[derive(Debug)]
pub struct MyCljRecur {
    pub ptr: *mut CljRecur,
}

impl MyCljRecur {
    pub fn new() -> Self {
        Self {
            ptr: Box::into_raw(Box::new(CljRecur::new())),
        }
    }

    pub fn set_func_cell_body(&self, func_cell_body: Rc<CljCell>) {
        unsafe {
            //(*self.ptr).ht.get(key).unwrap()
            (*self.ptr).func_cell_body = func_cell_body
        }
    }

    pub fn set_clj_cell(&self, clj_cell: Rc<CljCell>) {
        unsafe {
            //(*self.ptr).ht.get(key).unwrap()
            (*self.ptr).set_clj_cell(clj_cell)
        }
    }

    pub fn get_func_cell_body(&self) -> &Rc<CljCell> {
        //&self.func_cell_body
        unsafe {
            &(*self.ptr).get_func_cell_body()
        }
    }

    pub fn get_clj_cell(&self) -> &Rc<CljCell> {
        unsafe {
            &(*self.ptr).get_clj_cell()
        }
    }

    pub fn get_clj_func_param_list(&self) -> &Vec<Rc<CljFuncParam>> {
        unsafe {
            &(*self.ptr).get_clj_func_param_list()
        }
    }

    pub fn set_clj_func_param_list(&self, clj_func_param_list: Vec<Rc<CljFuncParam>>) {
        unsafe {
            //(*self.ptr).ht.get(key).unwrap()
            (*self.ptr).clj_func_param_list = clj_func_param_list
        }
    }

    /**
     * 获取 ht 中的值
     * */
    pub fn get_ht_value(&self, key: &i32) -> &String {
        unsafe {
            (*self.ptr).ht.get(key).unwrap()
        }
    }

    /**
     * 添加值
     * */
    pub fn insert_ht(&self, key: i32, vs: String) -> Option<String> {
        unsafe {
            (*self.ptr).ht.insert(key, vs)
        }
    }
}

// 手动实现 Drop 释放内存
impl Drop for MyCljRecur {
    fn drop(&mut self) {
        unsafe {
            let _ = Box::from_raw(self.ptr);
        }
    }
}

/**
 * MyClojure 解释器
 * */
pub struct MyClojureInterp {
    pub ptr: *mut FuncParams,
}

impl MyClojureInterp {
    pub fn new() -> Self {
        Self {
            ptr: Box::into_raw(Box::new(FuncParams::new())),
        }
    }

    pub fn set_vs(&self, key: String, vs: MyCljFunc) {
        unsafe {
            //(*(*self).ptr).set_vs(key, vs);
            let p = self.ptr;
            (*p).set_vs(key, vs);
        }
    }

    pub fn clj_list(&self, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        if !lst.is_empty() {
            //let ptr: *mut MyClojureInterp = self as *const MyClojureInterp as *mut MyClojureInterp;
            let ptr = self;
            match &*lst[0] {
                CljCell::Defn => return CljFunctions::clj_list_defn(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Symbol(lst_rs) => return MyFunctions::clj_list_symbol(ptr, lst_rs, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Addition => return MyMath::clj_list_addition(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Subtraction => return MyMath::clj_list_subtraction(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Multiplication => return MyMath::clj_list_mul(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Division => return MyMath::clj_list_div(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Cond => return MyLogic::clj_list_cond(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::IfClj => return MyLogic::clj_list_if(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::AndLgClj => return MyLogic::clj_list_and(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::OrLgClj => return MyLogic::clj_list_or(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::EqualsLgClj => return MyLogic::clj_list_equals(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::GreaterThanLgClj => return MyLogic::clj_list_greater_than(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::LessThanLgClj => return MyLogic::clj_list_less_than(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::GreaterEqualsLgClj => return MyLogic::clj_list_greater_equals(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::LessEqualsLgClj => return MyLogic::clj_list_less_equals(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::NotClj => return MyLogic::clj_list_not(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::IsNil => return MyLogic::clj_list_is_nil(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::LetClj => return MyClj::clj_list_let(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Recur => return MyClj::clj_list_recur(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::LoopClj => return MyClj::clj_list_loop(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::DoClj => return MyClj::clj_list_do(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::List(ls_vs) => return MyClj::clj_list_list(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::DefClj => return MyClj::clj_list_def(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Apply => return MyClj::clj_list_apply(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::FirstClj => return MyCljData::clj_list_first(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::RestClj => return MyCljData::clj_list_rest(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::ElseClj => return MyClj::clj_list_else(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::Anonymous(lst_vs) => return CljFunctions::clj_list_anonymous(ptr, lst, func_hs, clj_recur, rs.clone()),
                CljCell::CljList(lst_vs) => {
                    // 处理匿名函数
                    if let CljCell::FnClj = &*lst_vs[0] {
                        return CljFunctions::clj_list_fn(ptr, lst, func_hs, clj_recur, rs.clone());
                    } else {
                        for i in 0..lst_vs.len() {
                            if i == lst_vs.len() - 1 {
                                return self.eval(&lst_vs[i], func_hs, clj_recur, rs.clone());
                            } else {
                                self.eval(&lst_vs[i], func_hs, clj_recur, rs.clone());
                            }
                        }
                    }
                },
                CljCell::Defmacro => return MyMacro::clj_list_macro(ptr, lst, func_hs, clj_recur, rs.clone()),
                _ => return Rc::new(CljCell::Null),
            }
        }
        return Rc::new(CljCell::Null);
    }

    /**
     * 执行
     * */
    pub fn eval(&self, cell: &Rc<CljCell>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        match &**cell {
            CljCell::CljList(lst) => return self.clj_list(lst, func_hs, clj_recur, rs.clone()),
            CljCell::Symbol(lst_rs) => return MyFunctions::clj_list_symbol_1(self, lst_rs, func_hs, clj_recur, rs.clone()),
            _ => return cell.clone(),
        }
    }

    /**
     * 执行
     * */
    pub fn eval_an(&self, cell: &Rc<CljCell>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        match &**cell {
            CljCell::Anonymous(lst) => return self.clj_list(lst, func_hs, clj_recur, rs.clone()),

            _ => return cell.clone(),
        }
    }

    /**
     * 最终执行
     * */
    pub fn my_eval(&self, cell: Rc<CljCell>) -> Rc<CljCell> {
        let func_hs = MyFuncHs::new();
        let clj_recur = MyCljRecur::new();
        self.eval(&cell, &func_hs, &clj_recur, Rc::new(CljCell::Null))
    }
}

// 手动实现 Drop 释放内存
impl Drop for MyClojureInterp {
    fn drop(&mut self) {
        unsafe {
            let _ = Box::from_raw(self.ptr);
        }
    }
}









































